﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace SharpShare.Storage {
    public static class StorageMetadata {
        public static void SetMetadata(this IStorageItem item, IEnumerable<KeyValuePair<string, byte[]>> values) {
            if (item == null) throw new ArgumentNullException("item");
            if (values == null) throw new ArgumentNullException("values");

            item.ClearMetadata();

            foreach (var pair in values) {
                item.AddMetadata(pair.Key, pair.Value);
            }
        }

        public static IDictionary<string, byte[]> GetMetadata(this IStorageItem item) {
            if (item == null) throw new ArgumentNullException("item");

            Dictionary<string, byte[]> data = new Dictionary<string, byte[]>();

            foreach (string name in item.ListMetadata()) {
                data[name] = item.GetMetadata(name);
            }

            return data;
        }

        /// <summary>
        /// Removes all metadata from the storage item.
        /// </summary>
        /// <returns>
        /// True if all metadata was deleted, False if at least one metadata stream couldn't be deleted.
        /// </returns>
        public static bool ClearMetadata(this IStorageItem item) {
            if (item == null) {
                throw new ArgumentNullException("item");
            }

            var existingMetadata = item.ListMetadata().ToList();
            bool allDeleted = true;

            foreach (string name in existingMetadata) {
                bool deleted = false;

                try {
                    deleted = item.RemoveMetadata(name);
                } catch { }

                if (!deleted)
                    allDeleted = false;
            }

            return allDeleted;
        }

        /// <summary>
        /// Adds a single metadata entry to the storage item.
        /// </summary>
        public static void AddMetadata(this IStorageItem item, string name, string value) {
            if (item == null) throw new ArgumentNullException("item");
            if (name == null) throw new ArgumentNullException("name");

            if (value == null) {
                item.RemoveMetadata(name);
                return;
            }

            using (Stream stream = item.OpenMetadata(name, StorageFileAccess.Write, StorageFileAccess.ReadWrite).CreateStream()) {
                stream.SetLength(0);
                using (StreamWriter writer = new StreamWriter(stream)) {
                    writer.Write(value);
                }
            }
        }

        /// <summary>
        /// Adds a single metadata entry to the storage item.
        /// </summary>
        public static void AddMetadata(this IStorageItem item, string name, byte[] value) {
            if (item == null) throw new ArgumentNullException("item");
            if (name == null) throw new ArgumentNullException("name");

            if (value == null) {
                item.RemoveMetadata(name);
                return;
            }

            using (Stream stream = item.OpenMetadata(name, StorageFileAccess.Write, StorageFileAccess.ReadWrite).CreateStream()) {
                stream.SetLength(0);
                stream.Write(value, 0, value.Length);
            }
        }

        public static byte[] GetMetadata(this IStorageItem item, string name) {
            if (item == null) throw new ArgumentNullException("item");
            if (name == null) throw new ArgumentNullException("name");

            IStorageDataProvider dataProvider = item.OpenMetadata(name, StorageFileAccess.Read, StorageFileAccess.ReadWrite, StorageFileMode.OpenExisting);

            if (dataProvider == null) {
                return null;
            }

            using (MemoryStream memStream = new MemoryStream()) {
                using (Stream stream = dataProvider.CreateStream()) {
                    stream.CopyTo(memStream);
                }

                return memStream.ToArray();
            }
        }

        public static string GetMetadataText(this IStorageItem item, string name) {
            if (item == null) throw new ArgumentNullException("item");
            if (name == null) throw new ArgumentNullException("name");

            IStorageDataProvider dataProvider = item.OpenMetadata(name, StorageFileAccess.Read, StorageFileAccess.ReadWrite, StorageFileMode.OpenExisting);

            if (dataProvider == null) {
                return null;
            }


            using (Stream stream = dataProvider.CreateStream()) {
                using (StreamReader reader = new StreamReader(stream)) {
                    return reader.ReadToEnd();
                }
            }
        }
    }
}
